﻿///------------------------------------
/// ControlCore ControlCommand.cs
///------------------------------------
namespace ControlCore
{
    using System;
    using System.Collections.Generic;
    using System.Linq;

    /// <summary>
    /// Control command type-safe enum class
    /// </summary>
    public sealed class ControlCommand
    {
        private static readonly Dictionary<string, ControlCommand> instance = new Dictionary<string, ControlCommand>();

        public static readonly ControlCommand Start = new ControlCommand(0, "Start", CommandType.FromController);
        public static readonly ControlCommand Stop = new ControlCommand(1, "Stop", CommandType.FromController);
        public static readonly ControlCommand Forward = new ControlCommand(2, "Forward", CommandType.FromController);
        public static readonly ControlCommand Backward = new ControlCommand(3, "Backward", CommandType.FromController);
        public static readonly ControlCommand Accelerate = new ControlCommand(4, "Accelerate", CommandType.FromController);
        public static readonly ControlCommand Decelerate = new ControlCommand(5, "Decelerate", CommandType.FromController);
        public static readonly ControlCommand Turn = new ControlCommand(6, "Turn", CommandType.FromController);

        /// <summary>
        /// Command integer value
        /// </summary>
        private readonly int value;

        /// <summary>
        /// Command name
        /// </summary>
        private readonly string name;

        /// <summary>
        /// Type of command
        /// </summary>
        private readonly CommandType type;

        private ControlCommand(int value, string name, CommandType type)
        {
            this.value = value;
            this.name = name;
            this.type = type;
            instance[name] = this;
        }

        /// <summary>
        /// Return collection of commands of specific type. 
        /// </summary>
        /// <param name="type">Command type</param>
        /// <returns></returns>
        public IEnumerable<ControlCommand> GetCommandsOfType(CommandType type)
        {
            return instance.Values.Where(x => x.type == type);
        }

        public static explicit operator ControlCommand(string name)
        {
            ControlCommand result;
            if (instance.TryGetValue(name, out result))
            {
                return result;
            }

            throw new InvalidCastException();
        }

        public static explicit operator ControlCommand(int value)
        {
            foreach (var controlCommandEntry in instance)
            {
                if (controlCommandEntry.Value.value == value)
                {
                    return controlCommandEntry.Value;
                }
            }

            throw new InvalidCastException();
        }

        public static explicit operator int(ControlCommand controlCommand)
        {
            ControlCommand result;
            if (instance.TryGetValue(controlCommand.name, out result))
            {
                return result.value;
            }

            throw new InvalidCastException();
        }

        public override string ToString()
        {
            return this.name;
        }
    }
}
